<!DOCTYPE html>
<html lang="en">
  <head>
    <title>  Reference</title>
    <link rel="stylesheet" type="text/css" href="css/jazzy.css" />
    <link rel="stylesheet" type="text/css" href="css/highlight.css" />
    <meta charset="utf-8">
    <script src="js/jquery.min.js" defer></script>
    <script src="js/jazzy.js" defer></script>
    
    <script src="js/lunr.min.js" defer></script>
    <script src="js/typeahead.jquery.js" defer></script>
    <script src="js/jazzy.search.js" defer></script>
  </head>
  <body>


    <a title="  Reference"></a>

    <header class="header">
      <p class="header-col header-col--primary">
        <a class="header-link" href="index.html">
          Wave
        </a>
         (100% documented)
      </p>
    
      <div class="header-col--secondary">
        <form role="search" action="search.json">
          <input type="text" placeholder="Search documentation" data-typeahead>
        </form>
      </div>
    
    
    </header>

    <p class="breadcrumbs">
      <a class="breadcrumb" href="index.html"> Reference</a>
      <img class="carat" src="img/carat.png" alt=""/>
        Reference
    </p>

    <div class="content-wrapper">
      <nav class="navigation">
        <ul class="nav-groups">
          <li class="nav-group-name">
            <a class="nav-group-name-link" href="Classes.html">Classes</a>
            <ul class="nav-group-tasks">
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Classes/LayerAnimator.html">LayerAnimator</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Classes/Spring.html">Spring</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Classes/SpringAnimator.html">SpringAnimator</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Classes/SpringAnimator/Event.html">– Event</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Classes/ViewAnimator.html">ViewAnimator</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Classes/Wave.html">Wave</a>
              </li>
            </ul>
          </li>
          <li class="nav-group-name">
            <a class="nav-group-name-link" href="Enums.html">Enumerations</a>
            <ul class="nav-group-tasks">
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Enums/AnimationMode.html">AnimationMode</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Enums/AnimatorState.html">AnimatorState</a>
              </li>
            </ul>
          </li>
          <li class="nav-group-name">
            <a class="nav-group-name-link" href="Extensions.html">Extensions</a>
            <ul class="nav-group-tasks">
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/CALayer.html">CALayer</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/CGFloat.html">CGFloat</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/CGPoint.html">CGPoint</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/CGRect.html">CGRect</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/CGSize.html">CGSize</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions.html#/s:4Wave14RGBAComponentsV">RGBAComponents</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/UIView.html">UIView</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Extensions/WaveColor.html">WaveColor</a>
              </li>
            </ul>
          </li>
          <li class="nav-group-name">
            <a class="nav-group-name-link" href="Functions.html">Functions</a>
            <ul class="nav-group-tasks">
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave4clip5value5lower5upperxx_xxtSFRzlF">clip(value:lower:upper:)</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave8clipUnit5valuexx_tSFRzlF">clipUnit(value:)</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave8mapRange_____4clipxx_xxxxSbtSFRzlF">mapRange(_:_:_:_:_:clip:)</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave8mapRange5value5inMin0E3Max03outF00hG04clipxx_xxxxSbtSFRzlF">mapRange(value:inMin:inMax:outMin:outMax:clip:)</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave7project5point8velocity16decelerationRateSo7CGPointVAG_AG12CoreGraphics7CGFloatVtF">project(point:velocity:decelerationRate:)</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave7project5value8velocity16decelerationRate12CoreGraphics7CGFloatVAH_A2HtF">project(value:velocity:decelerationRate:)</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Functions.html#/s:4Wave10rubberband5value5range8interval1c12CoreGraphics7CGFloatVAI_SNyAIGA2ItF">rubberband(value:range:interval:c:)</a>
              </li>
            </ul>
          </li>
          <li class="nav-group-name">
            <a class="nav-group-name-link" href="Protocols.html">Protocols</a>
            <ul class="nav-group-tasks">
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Protocols/SpringInterpolatable.html">SpringInterpolatable</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Protocols/VelocityProviding.html">VelocityProviding</a>
              </li>
            </ul>
          </li>
          <li class="nav-group-name">
            <a class="nav-group-name-link" href="Typealiases.html">Type Aliases</a>
            <ul class="nav-group-tasks">
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Typealiases.html#/WaveColor">WaveColor</a>
              </li>
              <li class="nav-group-task">
                <a class="nav-group-task-link" href="Typealiases.html#/s:4Wave0A5Colora">WaveColor</a>
              </li>
            </ul>
          </li>
        </ul>
      </nav>
      <article class="main-content">

        <section class="section">
          <div class="section-content top-matter">
            
            <p align="center">
    <img width="400" src="./Assets/Logo.png">
</p>
<h2 id='wave' class='heading'>Wave</h2>

<p>Wave is a spring-based animation engine for iOS, iPadOS, and macOS. It makes it easy to create fluid, interactive, and interruptible animations that feel great.</p>

<p>Wave has no external dependencies, and can be easily dropped into existing UIKit, SwiftUI, or AppKit based projects and apps.</p>

<p>The core feature of Wave is that all animations are <em>re-targetable</em>, meaning that you can change an animation’s destination value in-flight, and the animation will gracefully <em>redirect</em> to that new value.</p>

<ul>
<li><a href="#features">Understanding Retargeting</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#documentation">Documentation</a></li>
<li><a href="#getting-started">Getting Started</a>

<ul>
<li><a href="#block-based-animation">Block-Based Animation</a></li>
<li><a href="#property-based-animation">Property-Based Animation</a></li>
</ul></li>
<li><a href="#example-code">Example Code</a></li>
</ul>
<h4 id='understanding-retargeting' class='heading'>Understanding Retargeting</h4>

<p>Consider these demos of the iOS Picture-in-Picture feature. The screen on the left is created with standard UIKit animations, and the one on the right is created with Wave.</p>

<p>Though both are “interruptible”, the Wave-based implementation handles the interruption much better, and fluidly <em>arcs</em> to its new destination. The UIKit animation feels stiff and jerky in comparison.</p>

<p>At its core, <a href="https://developer.apple.com/videos/play/wwdc2018/803/">retargeting</a> is the process of preserving an animation’s velocity even as its target changes, which Wave does automatically.</p>

<p><img src="./Assets/Retargeting.gif" alt="Demo"></p>
<h3 id='installation' class='heading'>Installation</h3>

<p>Add Wave to your app&rsquo;s <code>Package.swift</code> file, or selecting <code>File -&gt; Add Packages</code> in Xcode:</p>
<pre class="highlight swift"><code><span class="o">.</span><span class="nf">package</span><span class="p">(</span><span class="nv">url</span><span class="p">:</span> <span class="s">"https://github.com/jtrivedi/Wave"</span><span class="p">)</span>
</code></pre>

<p>If you clone the repo, you can run the sample app, which contains a few interactive demos to understand what Wave provides.</p>

<p>Note: To enable high frame-rate animations on ProMotion devices (i.e. 120 fps animation), you&rsquo;ll need to add a key/value pair in your <code>Info.plist</code>. Set the key <code>CADisableMinimumFrameDuration</code> to <code>true</code>. Without this entry, animations will be capped at 60 fps.</p>
<h3 id='documentation' class='heading'>Documentation</h3>

<p>There’s a full Wave <a href="https://Wave-jtrivedi.structure.sh">documentation site</a> available for full API and usage documentation.</p>
<h3 id='getting-started' class='heading'>Getting Started</h3>

<p>There are two ways you can interact with Wave, depending on your needs: the block-based and property-based animations:</p>
<h4 id='block-based-animation' class='heading'>Block-Based Animation</h4>

<p>The easiest way to get started is by using Wave’s block-based APIs that resemble the <code>UIView.animateWithDuration()</code> APIs.</p>

<p>This API lets you animate several common UIView and CALayer properties, like <code>frame</code>, <code>center</code>, <code>scale</code>, <code>backgroundColor</code>, and more.</p>

<p>For these supported properties, Wave will create, manage, and execute the required spring animations under-the-hood.</p>

<p>For example, animating the above PiP view to its final destination is extremely simple:</p>
<pre class="highlight swift"><code><span class="k">if</span> <span class="n">panGestureRecognizer</span><span class="o">.</span><span class="n">state</span> <span class="o">==</span> <span class="o">.</span><span class="n">ended</span> <span class="p">{</span>

    <span class="c1">// Create a spring with some bounciness. `response` affects the animation's duration.</span>
    <span class="k">let</span> <span class="nv">animatedSpring</span> <span class="o">=</span> <span class="kt">Spring</span><span class="p">(</span><span class="nv">dampingRatio</span><span class="p">:</span> <span class="mf">0.68</span><span class="p">,</span> <span class="nv">response</span><span class="p">:</span> <span class="mf">0.80</span><span class="p">)</span>

    <span class="c1">// Get the gesture's lift-off velocity, and pass it into the Wave animation.</span>
    <span class="k">let</span> <span class="nv">gestureVelocity</span> <span class="o">=</span> <span class="n">panGestureRecognizer</span><span class="o">.</span><span class="nf">velocity</span><span class="p">(</span><span class="nv">in</span><span class="p">:</span> <span class="n">view</span><span class="p">)</span>

    <span class="kt">Wave</span><span class="o">.</span><span class="nf">animate</span><span class="p">(</span><span class="nv">withSpring</span><span class="p">:</span> <span class="n">animatedSpring</span><span class="p">,</span> <span class="nv">gestureVelocity</span><span class="p">:</span> <span class="n">gestureVelocity</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// Update animatable properties on the view's `animator` property, _not_ the view itself.</span>
        <span class="n">pipView</span><span class="o">.</span><span class="n">animator</span><span class="o">.</span><span class="n">center</span> <span class="o">=</span> <span class="n">pipViewDestination</span>     <span class="c1">// Some target CGPoint that you calculate.</span>
        <span class="n">pipView</span><span class="o">.</span><span class="n">animator</span><span class="o">.</span><span class="n">scale</span> <span class="o">=</span> <span class="kt">CGPoint</span><span class="p">(</span><span class="nv">x</span><span class="p">:</span> <span class="mf">1.1</span><span class="p">,</span> <span class="nv">y</span><span class="p">:</span> <span class="mf">1.1</span><span class="p">)</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>

<p>Note that at <em>any</em> time, you can <em>retarget</em> the view’s <code>center</code> property to somewhere else, and it’ll gracefully animate.</p>
<h5 id='supported-animatable-properties' class='heading'>Supported Animatable Properties</h5>

<p>The block-based API currently supports animating the following properties. For other properties, you can use the property-based animation API below.</p>

<ul>
<li><code>frame</code></li>
<li><code>bounds</code></li>
<li><code>center</code></li>
<li><code>origin</code></li>
<li><code>alpha</code></li>
<li><code>backgroundColor</code></li>
<li><code>cornerRadius</code></li>
<li><code>scale</code></li>
<li><code>translation</code></li>
<li><code>shadowColor/radius/offset/opacity</code></li>
<li><code>borderColor/borderWidth</code></li>
</ul>

<p>Upcoming properties:</p>

<ul>
<li><code>rotation</code></li>
</ul>
<h4 id='property-based-animation' class='heading'>Property-Based Animation</h4>

<p>While the block-based API is often most convenient, you may want to animate something that the block-based API doesn’t yet support (e.x. rotation). Or, you may want the flexibility of getting the intermediate spring values and driving an animation yourself (e.x. a progress value).</p>

<p>For example, to draw the orange path of the PiP demo, we need to know the value of every <code>CGPoint</code> from the view’s initial center, to its destination center:</p>
<pre class="highlight swift"><code><span class="c1">// When the gesture ends, create a `CGPoint` animator from the PiP view's initial center, to its target.</span>
<span class="c1">// The `valueChanged` callback provides the intermediate locations of the callback, allowing us to draw the path.</span>

<span class="k">let</span> <span class="nv">positionAnimator</span> <span class="o">=</span> <span class="kt">SpringAnimator</span><span class="o">&lt;</span><span class="kt">CGPoint</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">spring</span><span class="p">:</span> <span class="n">animatedSpring</span><span class="p">)</span>
<span class="n">positionAnimator</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">pipView</span><span class="o">.</span><span class="n">center</span>       <span class="c1">// The presentation value</span>
<span class="n">positionAnimator</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">pipViewDestination</span>  <span class="c1">// The target value</span>
<span class="n">positionAnimator</span><span class="o">.</span><span class="n">velocity</span> <span class="o">=</span> <span class="n">gestureVelocity</span>

<span class="n">positionAnimator</span><span class="o">.</span><span class="n">valueChanged</span> <span class="o">=</span> <span class="p">{</span> <span class="p">[</span><span class="k">weak</span> <span class="k">self</span><span class="p">]</span> <span class="n">location</span> <span class="k">in</span>
    <span class="k">self</span><span class="p">?</span><span class="o">.</span><span class="nf">drawPathPoint</span><span class="p">(</span><span class="nv">at</span><span class="p">:</span> <span class="n">location</span><span class="p">)</span>
<span class="p">}</span>

<span class="n">positionAnimator</span><span class="o">.</span><span class="nf">start</span><span class="p">()</span>
</code></pre>
<h5 id='completion-blocks' class='heading'>Completion Blocks</h5>

<p>Both the block-based and property-based APIs support completion blocks. If an animation completes fully, the completion block’s <code>finished</code> flag will be true.</p>

<p>However, if an animation’s target was changed in-flight (“retargeted”), <code>finished</code> will be false, while <code>retargeted</code> will be true.</p>
<pre class="highlight swift"><code><span class="kt">Wave</span><span class="o">.</span><span class="nf">animate</span><span class="p">(</span><span class="nv">withSpring</span><span class="p">:</span> <span class="kt">Spring</span><span class="o">.</span><span class="n">defaultAnimated</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">myView</span><span class="o">.</span><span class="n">animator</span><span class="o">.</span><span class="n">backgroundColor</span> <span class="o">=</span> <span class="o">.</span><span class="n">systemBlue</span>
<span class="p">}</span> <span class="nv">completion</span><span class="p">:</span> <span class="p">{</span> <span class="n">finished</span><span class="p">,</span> <span class="n">retargeted</span> <span class="k">in</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">finished</span><span class="p">,</span> <span class="n">retargeted</span><span class="p">)</span>
<span class="p">}</span>
</code></pre>
<h3 id='example-code' class='heading'>Example Code</h3>

<p>Exploring the provided sample app is a great way to get started with Wave.</p>

<p>Simply open the <code><a href="Classes/Wave.html">Wave</a></code> Xcode project and hit “Run”. The full source code for the Picture-in-Picture demo is available there, too!</p>
<h3 id='acknowledgements' class='heading'>Acknowledgements</h3>

<p>Special thanks to <a href="https://github.com/boztalay">Ben Oztalay</a> for helping architect the underlying physics of Wave!</p>

          </div>
        </section>


      </article>
    </div>
    <section class="footer">
      <p>&copy; 2022 <a class="link" href="https://github.com/jtrivedi" target="_blank" rel="external noopener">Janum Trivedi</a>. All rights reserved. (Last updated: 2022-11-14)</p>
      <p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.2</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
    </section>
  </body>
</html>
